package com.example.demo.component;

import com.example.demo.config.AppValue;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.jdbc.Null;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.servlet.http.HttpSession;
import javax.websocket.Session;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class ChatRoom extends TextWebSocketHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserService userService;

    //记录当前上线的人的信息
    private static ConcurrentHashMap<Integer, WebSocketSession> onlineUsers = new ConcurrentHashMap<>();


    /**
     * 建立连接触发
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        try {

            //获取当前登录用户的信息(可能为 null -> 直接通过网址访问)
            UserInfo curUser = (UserInfo) session.getAttributes().get(AppValue.SESSION_KEY);
            //检验当前用户是否重复登录
            if(onlineUsers.get(curUser.getId()) != null) {
                session.sendMessage(new TextMessage(
                        objectMapper.writeValueAsString(AjaxResult.error(-1,"many", ""))));
                session.close();
                return;
            }
            //将当前用户登录的信息加入到 在线用户 中
            onlineUsers.put(curUser.getId(), session);
            //将当前用户的上线消息推送给除了自己以外的所有用户
            for(int key : onlineUsers.keySet()) {
                WebSocketSession sessionUser = onlineUsers.get(key);
                sessionUser.sendMessage(new TextMessage(
                        objectMapper.writeValueAsString(AjaxResult.success(curUser.getId(), "online",  curUser))));
            }
        } catch (NullPointerException e) {
            //防止当前用户未登录，获取到空对象
            e.printStackTrace();
            session.sendMessage(new TextMessage(
                    objectMapper.writeValueAsString(AjaxResult.error(-1, "exception", ""))));
        }
    }

    /**
     * 收到消息触发
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        UserInfo curUser = (UserInfo) session.getAttributes().get(AppValue.SESSION_KEY);
        //获取数据载荷
        String payLoad = message.getPayload();
        //将 json 格式解析成 AjaxResult 格式
        AjaxResult ajaxResult = objectMapper.readValue(payLoad, AjaxResult.class);
        //获取要发送的消息
        String msg = ajaxResult.getMsg();
        //获取对方信息
        UserInfo userInfo = userService.getUserInfoById(ajaxResult.getCode());
        //将对方消息发送给除了自己以外所有在线的人
        for(int key : onlineUsers.keySet()) {
            if(key != curUser.getId()) {
                onlineUsers.get(key).sendMessage(new TextMessage(
                        objectMapper.writeValueAsString(AjaxResult.success(userInfo.getId(), msg, userInfo))
                ));
            }
        }
    }

    /**
     * 异常触发
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try {
            UserInfo curUser = (UserInfo) session.getAttributes().get(AppValue.SESSION_KEY);
            onlineUsers.remove(curUser.getId());
            for(int key : onlineUsers.keySet()) {
                WebSocketSession userSession = onlineUsers.get(key);
                userSession.sendMessage(new TextMessage(
                        objectMapper.writeValueAsString(AjaxResult.success(curUser.getId(), "out", curUser))
                ));
            }
        } catch(NullPointerException e) {
            e.printStackTrace();
            session.sendMessage(new TextMessage(
                    objectMapper.writeValueAsString(AjaxResult.error(-1, "exception", ""))
            ));
        }
    }

    /**
     * 断开连接触发
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            //获取当前登录用户信息
            UserInfo curUser = (UserInfo) session.getAttributes().get(AppValue.SESSION_KEY);
            //从 在线用户 中将当前用户踢出
            onlineUsers.remove(curUser.getId());
            //给其他用户推送下线消息
            for(int key : onlineUsers.keySet()) {
                WebSocketSession userSession = onlineUsers.get(key);
                userSession.sendMessage(new TextMessage(
                        objectMapper.writeValueAsString(AjaxResult.success(1, "out", curUser))));
            }
        } catch(NullPointerException e) {
            e.printStackTrace();
            session.sendMessage(new TextMessage(
                    objectMapper.writeValueAsString(AjaxResult.error(-1, "exception", ""))
            ));
        }
    }

}
